home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / pico / tcap.c < prev    next >
C/C++ Source or Header  |  1996-03-15  |  15KB  |  663 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: tcap.c,v 4.26 1996/03/15 07:41:11 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Display routines
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*    tcap:    Unix V5, V7 and BS4.2 Termcap video driver
  31.         for MicroEMACS
  32. */
  33.  
  34. #define    termdef    1            /* don't define "term" external */
  35.  
  36. #include    <stdio.h>
  37. #include        <signal.h>
  38. #include    "osdep.h"
  39. #include        "pico.h"
  40. #include    "estruct.h"
  41. #include        "edef.h"
  42.  
  43. #if TERMCAP
  44. #define    MARGIN    8
  45. #define    SCRSIZ    64
  46. #define    MROW    2
  47. #define BEL     0x07
  48. #define ESC     0x1B
  49.  
  50. extern int      ttopen();
  51. extern int      ttgetc();
  52. extern int      ttputc();
  53. extern int      ttflush();
  54. extern int      ttclose();
  55.  
  56. static int      tcapmove();
  57. static int      tcapeeol();
  58. static int      tcapeeop();
  59. static int      tcapbeep();
  60. static int    tcaprev();
  61. static int      tcapopen();
  62. static int      tcapclose();
  63. static void     setup_dflt_pico_esc_seq();
  64.  
  65. extern int      tput();
  66. extern char     *tgoto();
  67.  
  68. #define TCAPSLEN 315
  69. char tcapbuf[TCAPSLEN];
  70. char *UP, PC, *CM, *CE, *CL, *SO, *SE;
  71. /* 
  72.  * PICO extentions 
  73.  */
  74. char    *DL,            /* delete line */
  75.     *AL,            /* insert line */
  76.     *CS,            /* define a scrolling region, vt100 */
  77.     *IC,            /* insert character, preferable to : */
  78.     *IM,            /* set insert mode and, */
  79.     *EI,            /* end insert mode */
  80.     *DC,            /* delete character */
  81.     *DM,            /* set delete mode and, */
  82.     *ED,            /* end delete mode */
  83.     *SF,            /* scroll text up */
  84.     *SR,            /* scroll text down */
  85.     *TI,            /* string to start termcap */
  86.         *TE;            /* string to end termcap */
  87.  
  88.  
  89. TERM term = {
  90.         NROW-1,
  91.         NCOL,
  92.     MARGIN,
  93.     SCRSIZ,
  94.     MROW,
  95.         tcapopen,
  96.         tcapclose,
  97.         ttgetc,
  98.         ttputc,
  99.         ttflush,
  100.         tcapmove,
  101.         tcapeeol,
  102.         tcapeeop,
  103.         tcapbeep,
  104.         tcaprev
  105. };
  106.  
  107.  
  108. /*
  109.  * Add default keypad sequences to the trie.
  110.  */
  111. static void
  112. setup_dflt_pico_esc_seq()
  113. {
  114.     /*
  115.      * this is sort of a hack, but it allows us to use
  116.      * the function keys on pc's running telnet
  117.      */
  118.  
  119.     /* 
  120.      * UW-NDC/UCS vt10[02] application mode.
  121.      */
  122.     kpinsert(&pico_kbesc, "\033OP", F1);
  123.     kpinsert(&pico_kbesc, "\033OQ", F2);
  124.     kpinsert(&pico_kbesc, "\033OR", F3);
  125.     kpinsert(&pico_kbesc, "\033OS", F4);
  126.     kpinsert(&pico_kbesc, "\033Op", F5);
  127.     kpinsert(&pico_kbesc, "\033Oq", F6);
  128.     kpinsert(&pico_kbesc, "\033Or", F7);
  129.     kpinsert(&pico_kbesc, "\033Os", F8);
  130.     kpinsert(&pico_kbesc, "\033Ot", F9);
  131.     kpinsert(&pico_kbesc, "\033Ou", F10);
  132.     kpinsert(&pico_kbesc, "\033Ov", F11);
  133.     kpinsert(&pico_kbesc, "\033Ow", F12);
  134.  
  135.     /*
  136.      * DC vt100, ANSI and cursor key mode.
  137.      */
  138.     kpinsert(&pico_kbesc, "\033OA", K_PAD_UP);
  139.     kpinsert(&pico_kbesc, "\033OB", K_PAD_DOWN);
  140.     kpinsert(&pico_kbesc, "\033OC", K_PAD_RIGHT);
  141.     kpinsert(&pico_kbesc, "\033OD", K_PAD_LEFT);
  142.  
  143.     /*
  144.      * special keypad functions
  145.      */
  146.     kpinsert(&pico_kbesc, "\033[4J", K_PAD_PREVPAGE);
  147.     kpinsert(&pico_kbesc, "\033[3J", K_PAD_NEXTPAGE);
  148.     kpinsert(&pico_kbesc, "\033[2J", K_PAD_HOME);
  149.     kpinsert(&pico_kbesc, "\033[N",  K_PAD_END);
  150.  
  151.     /* 
  152.      * ANSI mode.
  153.      */
  154.     kpinsert(&pico_kbesc, "\033[=a", F1);
  155.     kpinsert(&pico_kbesc, "\033[=b", F2);
  156.     kpinsert(&pico_kbesc, "\033[=c", F3);
  157.     kpinsert(&pico_kbesc, "\033[=d", F4);
  158.     kpinsert(&pico_kbesc, "\033[=e", F5);
  159.     kpinsert(&pico_kbesc, "\033[=f", F6);
  160.     kpinsert(&pico_kbesc, "\033[=g", F7);
  161.     kpinsert(&pico_kbesc, "\033[=h", F8);
  162.     kpinsert(&pico_kbesc, "\033[=i", F9);
  163.     kpinsert(&pico_kbesc, "\033[=j", F10);
  164.     kpinsert(&pico_kbesc, "\033[=k", F11);
  165.     kpinsert(&pico_kbesc, "\033[=l", F12);
  166.  
  167.     /*
  168.      * DEC vt100, ANSI, cursor key mode reset.
  169.      */
  170.     kpinsert(&pico_kbesc, "\033[A", K_PAD_UP);
  171.     kpinsert(&pico_kbesc, "\033[B", K_PAD_DOWN);
  172.     kpinsert(&pico_kbesc, "\033[C", K_PAD_RIGHT);
  173.     kpinsert(&pico_kbesc, "\033[D", K_PAD_LEFT);
  174.  
  175.     /*
  176.      * DEC vt52 mode.
  177.      */
  178.     kpinsert(&pico_kbesc, "\033A", K_PAD_UP);
  179.     kpinsert(&pico_kbesc, "\033B", K_PAD_DOWN);
  180.     kpinsert(&pico_kbesc, "\033C", K_PAD_RIGHT);
  181.     kpinsert(&pico_kbesc, "\033D", K_PAD_LEFT);
  182.  
  183.     /*
  184.      * DEC vt52 application keys, and some Zenith 19.
  185.      */
  186.     kpinsert(&pico_kbesc, "\033?r", K_PAD_DOWN);
  187.     kpinsert(&pico_kbesc, "\033?t", K_PAD_LEFT);
  188.     kpinsert(&pico_kbesc, "\033?v", K_PAD_RIGHT);
  189.     kpinsert(&pico_kbesc, "\033?x", K_PAD_UP);
  190.  
  191.     /*
  192.      * Sun Console sequences.
  193.      */
  194.     kpinsert(&pico_kbesc, "\033[1",   K_SWALLOW_TIL_Z);
  195.     kpinsert(&pico_kbesc, "\033[215", K_SWALLOW_UP);
  196.     kpinsert(&pico_kbesc, "\033[217", K_SWALLOW_LEFT);
  197.     kpinsert(&pico_kbesc, "\033[219", K_SWALLOW_RIGHT);
  198.     kpinsert(&pico_kbesc, "\033[221", K_SWALLOW_DOWN);
  199.  
  200.     /*
  201.      * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
  202.      */
  203.     kpinsert(&pico_kbesc, "\033_", K_KERMIT);
  204.  
  205.     /*
  206.      * Fake a control character.
  207.      */
  208.     kpinsert(&pico_kbesc, "\033\033", K_DOUBLE_ESC);
  209. }
  210.  
  211.  
  212. static int
  213. tcapopen()
  214. {
  215.     char   *t, *p, *tgetstr();
  216.     char    tcbuf[1024];
  217.     char   *tv_stype;
  218.     char    err_str[72];
  219.     char   *getenv();
  220.     int     row, col;
  221.     char   *KU, *KD, *KL, *KR,
  222.        *KPPU, *KPPD, *KPHOME, *KPEND, *KPDEL,
  223.        *KF1, *KF2, *KF3, *KF4, *KF5, *KF6,
  224.        *KF7, *KF8, *KF9, *KF10, *KF11, *KF12;
  225.  
  226.     /*
  227.      * determine the terminal's communication speed and decide
  228.      * if we need to do optimization ...
  229.      */
  230.     optimize = ttisslow();
  231.  
  232.     if ((tv_stype = getenv("TERM")) == NULL){
  233.     if(Pmaster){
  234.         return(FALSE);
  235.     }
  236.     else{
  237.         puts("Environment variable TERM not defined!");
  238.         exit(1);
  239.     }
  240.     }
  241.  
  242.     if((tgetent(tcbuf, tv_stype)) != 1){
  243.     if(Pmaster){
  244.         return(FALSE);
  245.     }
  246.     else{
  247.         sprintf(err_str, "Unknown terminal type %s!", tv_stype);
  248.         puts(err_str);
  249.         exit(1);
  250.     }
  251.     }
  252.  
  253.     p = tcapbuf;
  254.     t = tgetstr("pc", &p);
  255.     if(t)
  256.       PC = *t;
  257.  
  258.     CL = tgetstr("cl", &p);
  259.     CM = tgetstr("cm", &p);
  260.     CE = tgetstr("ce", &p);
  261.     UP = tgetstr("up", &p);
  262.     SE = tgetstr("se", &p);
  263.     SO = tgetstr("so", &p);
  264.     DL = tgetstr("dl", &p);
  265.     AL = tgetstr("al", &p);
  266.     CS = tgetstr("cs", &p);
  267.     IC = tgetstr("ic", &p);
  268.     IM = tgetstr("im", &p);
  269.     EI = tgetstr("ei", &p);
  270.     DC = tgetstr("dc", &p);
  271.     DM = tgetstr("dm", &p);
  272.     ED = tgetstr("ed", &p);
  273.     SF = tgetstr("sf", &p);
  274.     SR = tgetstr("sr", &p);
  275.     TI = tgetstr("ti", &p);
  276.     TE = tgetstr("te", &p);
  277.  
  278.     row = tgetnum("li");
  279.     if(row == -1){
  280.     char *er;
  281.     int   rr;
  282.  
  283.     /* tgetnum failed, try $LINES */
  284.     er = getenv("LINES");
  285.     if(er && (rr = atoi(er)) > 0)
  286.       row = rr;
  287.     }
  288.     if(row >= 0)
  289.       row--;
  290.  
  291.     col = tgetnum("co");
  292.     if(col == -1){
  293.     char *ec;
  294.     int   cc;
  295.  
  296.     /* tgetnum failed, try $COLUMNS */
  297.     ec = getenv("COLUMNS");
  298.     if(ec && (cc = atoi(ec)) > 0)
  299.       col = cc;
  300.     }
  301.  
  302.     ttgetwinsz(&row, &col);
  303.     term.t_nrow = (short) row;
  304.     term.t_ncol = (short) col;
  305.  
  306.     eolexist = (CE != NULL);    /* will we be able to use clear to EOL? */
  307.     revexist = (SO != NULL);
  308.     if(DC == NULL && (DM == NULL || ED == NULL))
  309.       delchar = FALSE;
  310.     if(IC == NULL && (IM == NULL || EI == NULL))
  311.       inschar = FALSE;
  312.     if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
  313.       scrollexist = FALSE;
  314.  
  315.     if(CL == NULL || CM == NULL || UP == NULL){
  316.     if(Pmaster == NULL){
  317.         puts("Incomplete termcap entry\n");
  318.         exit(1);
  319.     }
  320.     }
  321.     else{
  322.     KPPU   = tgetstr("kP", &p);
  323.     KPPD   = tgetstr("kN", &p);
  324.     KPHOME = tgetstr("kh", &p);
  325.     KPEND  = tgetstr("kE", &p);
  326.     KPDEL  = tgetstr("kD", &p);
  327.     KU     = tgetstr("ku", &p);
  328.     KD     = tgetstr("kd", &p);
  329.     KL     = tgetstr("kl", &p);
  330.     KR     = tgetstr("kr", &p);
  331.     KF1    = tgetstr("k1", &p);
  332.     KF2    = tgetstr("k2", &p);
  333.     KF3    = tgetstr("k3", &p);
  334.     KF4    = tgetstr("k4", &p);
  335.     KF5    = tgetstr("k5", &p);
  336.     KF6    = tgetstr("k6", &p);
  337.     KF7    = tgetstr("k7", &p);
  338.     KF8    = tgetstr("k8", &p);
  339.     KF9    = tgetstr("k9", &p);
  340.     if((KF10 = tgetstr("k;", &p)) == NULL)
  341.       KF10 = tgetstr("k0", &p);
  342.     KF11   = tgetstr("F1", &p);
  343.     KF12   = tgetstr("F2", &p);
  344.  
  345. #ifndef TERMCAP_WINS
  346.     /*
  347.      * Add default keypad sequences to the trie.
  348.      * Since these come first, they will override any conflicting termcap
  349.      * or terminfo escape sequences defined below.  An escape sequence is
  350.      * considered conflicting if one is a prefix of the other.
  351.      * So, without TERMCAP_WINS, there will likely be some termcap/terminfo
  352.      * escape sequences that don't work, because they conflict with default
  353.      * sequences.
  354.      */
  355.     setup_dflt_pico_esc_seq();
  356. #endif /* !TERMCAP_WINS */
  357.  
  358.     /*
  359.      * add termcap escape sequences to the trie...
  360.      */
  361.     if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
  362.         kpinsert(&pico_kbesc, KU, K_PAD_UP);
  363.         kpinsert(&pico_kbesc, KD, K_PAD_DOWN);
  364.         kpinsert(&pico_kbesc, KL, K_PAD_LEFT);
  365.         kpinsert(&pico_kbesc, KR, K_PAD_RIGHT);
  366.     }
  367.  
  368.     if(KPPU != NULL && KPPD != NULL){
  369.         kpinsert(&pico_kbesc, KPPU, K_PAD_PREVPAGE);
  370.         kpinsert(&pico_kbesc, KPPD, K_PAD_NEXTPAGE);
  371.     }
  372.  
  373.     kpinsert(&pico_kbesc, KPHOME, K_PAD_HOME);
  374.     kpinsert(&pico_kbesc, KPEND,  K_PAD_END);
  375.     kpinsert(&pico_kbesc, KPDEL,  K_PAD_DELETE);
  376.  
  377.     kpinsert(&pico_kbesc, KF1,  F1);
  378.     kpinsert(&pico_kbesc, KF2,  F2);
  379.     kpinsert(&pico_kbesc, KF3,  F3);
  380.     kpinsert(&pico_kbesc, KF4,  F4);
  381.     kpinsert(&pico_kbesc, KF5,  F5);
  382.     kpinsert(&pico_kbesc, KF6,  F6);
  383.     kpinsert(&pico_kbesc, KF7,  F7);
  384.     kpinsert(&pico_kbesc, KF8,  F8);
  385.     kpinsert(&pico_kbesc, KF9,  F9);
  386.     kpinsert(&pico_kbesc, KF10, F10);
  387.     kpinsert(&pico_kbesc, KF11, F11);
  388.     kpinsert(&pico_kbesc, KF12, F12);
  389.     }
  390.  
  391.     /*
  392.      * Initialize UW-modified NCSA telnet to use it's functionkeys
  393.      */
  394.     if(gmode&MDFKEY && Pmaster == NULL)
  395.       puts("\033[99h");
  396.  
  397. #ifdef TERMCAP_WINS
  398.     /*
  399.      * Add default keypad sequences to the trie.
  400.      * Since these come after the termcap/terminfo escape sequences above,
  401.      * the termcap/info sequences will override any conflicting default
  402.      * escape sequences defined here.
  403.      * So, with TERMCAP_WINS, some of the default sequences will be missing.
  404.      * This means that you'd better get all of your termcap/terminfo entries
  405.      * correct if you define TERMCAP_WINS.
  406.      */
  407.     setup_dflt_pico_esc_seq();
  408. #endif /* TERMCAP_WINS */
  409.  
  410.     if (p >= &tcapbuf[TCAPSLEN]){
  411.     if(Pmaster == NULL){
  412.         puts("Terminal description too big!\n");
  413.         exit(1);
  414.     }
  415.     }
  416.  
  417.     ttopen();
  418.  
  419.     if(TI && !Pmaster) {
  420.     putpad(TI);            /* any init termcap requires */
  421.     if (CS)
  422.       putpad(tgoto(CS, term.t_nrow, 0)) ;
  423.     }
  424. }
  425.  
  426.  
  427. static int
  428. tcapclose()
  429. {
  430.     if(!Pmaster){
  431.     if(gmode&MDFKEY)
  432.       puts("\033[99l");        /* reset UW-NCSA telnet keys */
  433.  
  434.     if(TE)                /* any cleanup termcap requires */
  435.       putpad(TE);
  436.     }
  437.  
  438.     kbdestroy(pico_kbesc);        /* clean up key board sequence trie */
  439.     pico_kbesc = NULL;
  440.     ttclose();
  441. }
  442.  
  443.  
  444.  
  445. /*
  446.  * tcapinsert - insert a character at the current character position.
  447.  *              IC takes precedence.
  448.  */
  449. tcapinsert(ch)
  450. register char    ch;
  451. {
  452.     if(IC != NULL){
  453.     putpad(IC);
  454.     ttputc(ch);
  455.     }
  456.     else{
  457.     putpad(IM);
  458.     ttputc(ch);
  459.     putpad(EI);
  460.     }
  461. }
  462.  
  463.  
  464. /*
  465.  * tcapdelete - delete a character at the current character position.
  466.  */
  467. tcapdelete()
  468. {
  469.     if(DM == NULL && ED == NULL)
  470.       putpad(DC);
  471.     else{
  472.     putpad(DM);
  473.     putpad(DC);
  474.     putpad(ED);
  475.     }
  476. }
  477.  
  478.  
  479. /*
  480.  * o_scrolldown - open a line at the given row position.
  481.  *                use either region scrolling or deleteline/insertline
  482.  *                to open a new line.
  483.  */
  484. o_scrolldown(row, n)
  485. register int row;
  486. register int n;
  487. {
  488.     register int i;
  489.  
  490.     if(CS != NULL){
  491.     putpad(tgoto(CS, term.t_nrow - (term.t_mrow+1), row));
  492.     tcapmove(row, 0);
  493.     for(i = 0; i < n; i++)
  494.       putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
  495.     putpad(tgoto(CS, term.t_nrow, 0));
  496.     tcapmove(row, 0);
  497.     }
  498.     else{
  499.     /*
  500.      * this code causes a jiggly motion of the keymenu when scrolling
  501.      */
  502.     for(i = 0; i < n; i++){
  503.         tcapmove(term.t_nrow - (term.t_mrow+1), 0);
  504.         putpad(DL);
  505.         tcapmove(row, 0);
  506.         putpad(AL);
  507.     }
  508. #ifdef    NOWIGGLYLINES
  509.     /*
  510.      * this code causes a sweeping motion up and down the display
  511.      */
  512.     tcapmove(term.t_nrow - term.t_mrow - n, 0);
  513.     for(i = 0; i < n; i++)
  514.       putpad(DL);
  515.     tcapmove(row, 0);
  516.     for(i = 0; i < n; i++)
  517.       putpad(AL);
  518. #endif
  519.     }
  520. }
  521.  
  522.  
  523. /*
  524.  * o_scrollup - open a line at the given row position.
  525.  *              use either region scrolling or deleteline/insertline
  526.  *              to open a new line.
  527.  */
  528. o_scrollup(row, n)
  529. register int row;
  530. register int n;
  531. {
  532.     register int i;
  533.  
  534.     if(CS != NULL){
  535.     putpad(tgoto(CS, term.t_nrow - (term.t_mrow+1), row));
  536.     /* setting scrolling region moves cursor to home */
  537.     tcapmove(term.t_nrow-(term.t_mrow+1), 0);
  538.     for(i = 0;i < n; i++)
  539.       putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
  540.     putpad(tgoto(CS, term.t_nrow, 0));
  541.     tcapmove(2, 0);
  542.     }
  543.     else{
  544.     for(i = 0; i < n; i++){
  545.         tcapmove(row, 0);
  546.         putpad(DL);
  547.         tcapmove(term.t_nrow - (term.t_mrow+1), 0);
  548.         putpad(AL);
  549.     }
  550. #ifdef  NOWIGGLYLINES
  551.     /* see note above */
  552.     tcapmove(row, 0);
  553.     for(i = 0; i < n; i++)
  554.       putpad(DL);
  555.     tcapmove(term.t_nrow - term.t_mrow - n, 0);
  556.     for(i = 0;i < n; i++)
  557.       putpad(AL);
  558. #endif
  559.     }
  560. }
  561.  
  562.  
  563. /*
  564.  * o_insert - use termcap info to optimized character insert
  565.  *            returns: true if it optimized output, false otherwise
  566.  */
  567. o_insert(c)
  568. char c;
  569. {
  570.     if(inschar){
  571.     tcapinsert(c);
  572.     return(1);            /* no problems! */
  573.     }
  574.  
  575.     return(0);                /* can't do it. */
  576. }
  577.  
  578.  
  579. /*
  580.  * o_delete - use termcap info to optimized character insert
  581.  *            returns true if it optimized output, false otherwise
  582.  */
  583. o_delete()
  584. {
  585.     if(delchar){
  586.     tcapdelete();
  587.     return(1);            /* deleted, no problem! */
  588.     }
  589.  
  590.     return(0);                /* no dice. */
  591. }
  592.  
  593.  
  594. static int
  595. tcapmove(row, col)
  596. register int row, col;
  597. {
  598.     putpad(tgoto(CM, col, row));
  599. }
  600.  
  601.  
  602. static int
  603. tcapeeol()
  604. {
  605.     putpad(CE);
  606. }
  607.  
  608.  
  609. static int
  610. tcapeeop()
  611. {
  612.     putpad(CL);
  613. }
  614.  
  615.  
  616. static int
  617. tcaprev(state)        /* change reverse video status */
  618. int state;            /* FALSE = normal video, TRUE = reverse video */
  619. {
  620.     static int cstate = FALSE;
  621.  
  622.     if(state == cstate)        /* no op if already set! */
  623.       return(0);
  624.  
  625.     if(cstate = state){        /* remember last setting */
  626.     if (SO != NULL)
  627.       putpad(SO);
  628.     } 
  629.     else{
  630.     if (SE != NULL)
  631.       putpad(SE);
  632.     }
  633. }
  634.  
  635.  
  636. static int
  637. tcapbeep()
  638. {
  639.     ttputc(BEL);
  640. }
  641.  
  642.  
  643. putpad(str)
  644. char    *str;
  645. {
  646.     tputs(str, 1, ttputc);
  647. }
  648.  
  649.  
  650. putnpad(str, n)
  651. char    *str;
  652. {
  653.     tputs(str, n, ttputc);
  654. }
  655.  
  656. #else
  657.  
  658. hello()
  659. {
  660. }
  661.  
  662. #endif /* TERMCAP */
  663.